<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>Module: Terminator</title>
  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  <meta http-equiv="Content-Script-Type" content="text/javascript" />
  <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
  <script type="text/javascript">
  // <![CDATA[

  function popupCode( url ) {
    window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
  }

  function toggleCode( id ) {
    if ( document.getElementById )
      elem = document.getElementById( id );
    else if ( document.all )
      elem = eval( "document.all." + id );
    else
      return false;

    elemStyle = elem.style;
    
    if ( elemStyle.display != "block" ) {
      elemStyle.display = "block"
    } else {
      elemStyle.display = "none"
    }

    return true;
  }
  
  // Make codeblocks hidden by default
  document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
  
  // ]]>
  </script>

</head>
<body>



    <div id="classHeader">
        <table class="header-table">
        <tr class="top-aligned-row">
          <td><strong>Module</strong></td>
          <td class="class-name-in-header">Terminator</td>
        </tr>
        <tr class="top-aligned-row">
            <td><strong>In:</strong></td>
            <td>
                <a href="../files/lib/terminator_rb.html">
                lib/terminator.rb
                </a>
        <br />
            </td>
        </tr>

        </table>
    </div>
  <!-- banner header -->

  <div id="bodyContent">



  <div id="contextContent">

    <div id="description">
      <h1><a href="Terminator.html">Terminator</a></h1>
<h2>Synopsis</h2>
<p>
An external timeout mechanism based on processes and signals. Safe for
system calls. Safe for minors. but not very safe for misbehaving,
downtrodden zombied out processes.
</p>
<h2>Description</h2>
<p>
<a href="Terminator.html">Terminator</a> is a solution to the problem of
&#8216;how am I meant to kill a system call in Ruby!?&#8217;
</p>
<p>
Ruby (at least MRI) uses green threads to &quot;multitask&quot;. This means
that there is really only ever one ruby process running which then splits
up it&#8216;s processor time between all of it&#8216;s threads internally.
</p>
<p>
The processor then only has to deal with one ruby process and the ruby
process deals with all it&#8216;s threads. There are pros and cons to this
method, but that is not the point of this library.
</p>
<p>
The point is, that if you make a system call to an external resource from
ruby, then the kernel will go and make that call for ruby and NOT COME BACK
to ruby until that system call completes or fails. This can take a very
long time and is why your feeble attempts at using ruby&#8216;s internal
&quot;Timeout&quot; command has failed miserably at timing out your
external web service, database or network connections.
</p>
<p>
You see, Ruby just doesn&#8216;t get a chance to do anything as the kernel
goes &quot;I&#8216;m not going to talk to you again until your system calls
complete&quot;. Sort of a no win situation for Ruby.
</p>
<p>
That&#8216;s where <a href="Terminator.html">Terminator</a> comes in. Like
Arnie, he will come back. No matter what, and complete his mission, unless
he gets aborted before his timeout, you can trust <a
href="Terminator.html">Terminator</a> to thoroughly and without remorse,
nuke your misbehaving and timing out ruby processes efficiently, and
quickly.
</p>
<h2>How it Works</h2>
<p>
Basically we create a new terminator ruby process, separate to the existing
running ruby process that has a simple command of sleep for x seconds, and
then do a process TERM on the PID of the original ruby process that created
it.
</p>
<p>
If your process finishes before the timeout, it will kill the <a
href="Terminator.html">Terminator</a> first.
</p>
<p>
So really it is a race of who is going to win?
</p>
<p>
Word of warning though. <a href="Terminator.html">Terminator</a> is not
subtle. Don&#8216;t expect it to split hairs. Trying to give a process that
takes about 1 second to complete, a 2 second terminator&#8230; well&#8230;
odds are 50/50 on who is going to make it.
</p>
<p>
If you have a 1 second process, give it 3 seconds to complete. Arnie
doesn&#8216;t much care for casualties of war.
</p>
<p>
Another word of warning, if using <a href="Terminator.html">Terminator</a>
inside a loop, it is possible to exceed your open file limit. I have safely
tested looping 1000 times
</p>
<h2>URIS</h2>
<ul>
<li><a href="http://codeforpeople.com/lib/ruby">codeforpeople.com/lib/ruby</a>

</li>
<li><a
href="http://rubyforge.org/projects/codeforpeople">rubyforge.org/projects/codeforpeople</a>

</li>
</ul>
<h2>Usage</h2>
<p>
The terminator library is simple to use.
</p>
<pre>
 require 'terminator'
 Terminator.terminate(1) do
   sleep 4
   puts(&quot;I will never print&quot;)
 end
 #=&gt; Terminator::Error: Timeout out after 1s
</pre>
<p>
The above code snippet will raise a <a
href="Terminator/Error.html">Terminator::Error</a> as the
terminator&#8216;s timeout is 2 seconds and the block will take at least 4
to complete.
</p>
<p>
You can put error handling in with a simple begin / rescue block:
</p>
<pre>
 require 'terminator'
 begin
   Terminator.terminate(1) do
     sleep 4
     puts(&quot;I will never print&quot;)
   end
 rescue
   puts(&quot;I got terminated, but rescued myself.&quot;)
 end
 #=&gt; I got terminated, but rescued myself.
</pre>
<p>
The standard action on termination is to raise a <a
href="Terminator/Error.html">Terminator::Error</a>, however, this is just
an anonymous object that is called, so you can pass your own trap handling
by giving the terminator a lambda as an argument.
</p>
<pre>
 require 'terminator'
 custom_trap = lambda { eval(&quot;raise(RuntimeError, 'Oops... I failed...')&quot;) }
 Terminator.terminate(:seconds =&gt; 1, :trap =&gt; custom_trap) do
   sleep 10
 end
 #=&gt; RuntimeError: (eval):1:in `irb_binding': Oops... I failed...
</pre>

    </div>


   </div>

    <div id="method-list">
      <h3 class="section-bar">Methods</h3>

      <div class="name-list">
      <a href="#M000001">terminate</a>&nbsp;&nbsp;
      </div>
    </div>

  </div>


    <!-- if includes -->

    <div id="section">

    <div id="class-list">
      <h3 class="section-bar">Classes and Modules</h3>

      Class <a href="Terminator/Error.html" class="link">Terminator::Error</a><br />

    </div>

    <div id="constants-list">
      <h3 class="section-bar">Constants</h3>

      <div class="name-list">
        <table summary="Constants">
        <tr class="top-aligned-row context-row">
          <td class="context-item-name">Version</td>
          <td>=</td>
          <td class="context-item-value">'0.4.4'</td>
        </tr>
        </table>
      </div>
    </div>



      


    <!-- if method_list -->
    <div id="methods">
      <h3 class="section-bar">Public Instance methods</h3>

      <div id="method-M000001" class="method-detail">
        <a name="M000001"></a>

        <div class="method-heading">
          <a href="Terminator.src/M000001.html" target="Code" class="method-signature"
            onclick="popupCode('Terminator.src/M000001.html');return false;">
          <span class="method-name">terminate</span><span class="method-args">(options = {})</span>
          </a>
        </div>
      
        <div class="method-description">
          <p>
<a href="Terminator.html#M000001">Terminator.terminate</a> has two ways you
can call it. You can either just specify:
</p>
<pre>
 Terminator.terminate(seconds) { code_to_execute }
</pre>
<p>
where seconds is an integer number greater than or equal to 1. If you pass
a float in on seconds, <a href="Terminator.html">Terminator</a> will call
to_i on it and convert it to an integer. This is because <a
href="Terminator.html">Terminator</a> is not a precise tool, due to it
calling a new ruby instance, and spawning a new process, relying on split
second accuracy is a folly.
</p>
<p>
If you want to pass in the block, please use:
</p>
<pre>
 Terminator.terminate(:seconds =&gt; seconds, :trap =&gt; block) { code_to_execute }
</pre>
<p>
Where block is an anonymous method that gets called when the timeout
occurs.
</p>
        </div>
      </div>


    </div>


  </div>


<div id="validator-badges">
  <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
</div>

</body>
</html>